﻿using System.Runtime.InteropServices;
using System.Text;

using EnvDTE;

namespace PropertyAddin
{
	class ClassField
	{
		#region Private Members
		private CodeVariable m_Variable;
		private bool m_HasGetter;
		private bool m_HasSetter;
		private CodeProperty m_Property;
		private string m_PropertyName;
		private string m_ParameterName;
		private bool m_IsInherited;
		#endregion Private Members

		#region Constructors
		/// <summary>
		/// Creates an instance of class (or struct) field member with that variable member and
		/// indicating if the field is inherited or directly accessed in the class.
		/// </summary>
		/// <param name="variable"></param>
		/// <param name="isInherited"></param>
		public ClassField(CodeVariable variable, bool isInherited)
		{
			m_Variable = variable;
			m_PropertyName = GetPropertyName(m_Variable.Name);
			m_ParameterName = new string(char.ToLower(m_PropertyName[0]), 1);
			if (m_PropertyName.Length > 1)
				m_ParameterName = string.Concat(m_ParameterName, m_PropertyName.Substring(1));
			m_HasGetter = false;
			m_HasSetter = false;
			m_Property = null;
			m_IsInherited = isInherited;
		}
		#endregion Constructors

		#region Public Attributes
		/// <summary>
		/// Gets the name of the variable member.
		/// </summary>
		public string Name
		{
			get { return m_Variable.Name; }
		}

		/// <summary>
		/// Gets the variable member itself.
		/// </summary>
		public CodeVariable Variable
		{
			get { return m_Variable; }
		}

		/// <summary>
		/// Indicates if the associated property has a getter.
		/// </summary>
		public bool HasGetter
		{
			get { return m_HasGetter; }
		}

		/// <summary>
		/// Indicates if the associated property has a setter.
		/// </summary>
		public bool HasSetter
		{
			get { return m_HasSetter; }
		}

		/// <summary>
		/// Gets the associated property of the inner variable.
		/// </summary>
		public CodeProperty Property
		{
			get { return m_Property; }
			set
			{
				m_Property = value;
				if (m_Property == null)
				{
					m_HasGetter = false;
					m_HasSetter = false;
				}
				else
				{
					try
					{
						m_HasGetter = m_Property.Getter != null;
						m_HasSetter = m_Property.Setter != null;
					}
					catch (COMException)
					{
					}
				}
			}
		}

		/// <summary>
		/// Gets the property name extracted from the variable name.
		/// </summary>
		public string PropertyName
		{
			get { return m_PropertyName; }
		}

		/// <summary>
		/// Gets the constructor parameter name extracted from the variable name.
		/// </summary>
		public string ParameterName
		{
			get { return m_ParameterName; }
		}

		/// <summary>
		/// Indicates if the variable is accessed by inheritance or directly in the class.
		/// </summary>
		public bool IsInherited
		{
			get { return m_IsInherited; }
		}
		#endregion Public Attributes

		#region Public Methods
		/// <summary>
		/// Gets the inner text of the getter part of the property.
		/// </summary>
		/// <returns></returns>
		public string GetMethod(string template)
		{
            //return string.Format("get {{ return {0}; }}", m_Variable.Name);
            return string.Format(template, m_Variable.Name);
        }

		/// <summary>
		/// Gets the inner text of the setter part of the property.
		/// </summary>
		/// <param name="isInternal"></param>
		/// <returns></returns>
		public string SetMethod(bool isInternal, string template)
		{
            //return string.Format("{1}set {{ {0} = value; }}", m_Variable.Name, isInternal ? "internal "
            //    : string.Empty);
            return string.Format(template, m_Variable.Name, isInternal ? "internal " : string.Empty);
        }

		/// <summary>
		/// Gets the debugging string of the instance.
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			StringBuilder sb = new StringBuilder();

			sb.AppendFormat("Name: {0}, IsInherited: {1}", m_Variable.Name, m_IsInherited);
			if (m_Property != null)
			{
				sb.AppendFormat(", Property: {0}, Get: {1}, Set: {2}", m_Property.Name, m_HasGetter,
					m_HasSetter);
			}
			return sb.ToString();
		}
		#endregion Public Methods

		#region Static Methods
		/// <summary>
		/// Retrieves the property name corresponding to that variable member name.
		/// </summary>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		private static string GetPropertyName(string fieldname)
		{
			int num = 0;

			if (fieldname[0] == '_')
				num = 1;
			else if (fieldname.Length > 3 && fieldname[1] == '_')
			{
				num = 2;
				for (int i = 2; i < fieldname.Length; i++)
				{
					if (char.IsUpper(fieldname[i]))
					{
						num = i;
						break;
					}
				}
			}
			return (char.ToUpper(fieldname[num]) + fieldname.Substring(num + 1));
		}
		#endregion Static Methods
	}
}
